//
//  PlSInjector+PermissionRepair.m
//  Injector
//
//  Created by ∞ on 10/12/07.
//  Copyright 2007 Emanuele Vulcano (infinite-labs.net). All rights reserved.
//

#import "PlSInjector_PermissionRepair.h"
#import <sys/stat.h>

#define kPlSProcmodGroup (9)

@implementation PlSInjector (PermissionRepair)

- (BOOL) requiresAuthorizationWithError:(NSError**) error {
	NSString* exe = [[NSBundle mainBundle] executablePath];
	const char* exeC = [exe fileSystemRepresentation];
	
	struct stat stats;
	if (stat(exeC, &stats) == -1) {
		if (error) *error = [NSError errorWithDomain:NSPOSIXErrorDomain code:errno userInfo:nil];
		return NO;
	}
	
	BOOL needsAuth = (stats.st_gid != kPlSProcmodGroup)
	|| (stats.st_mode & 02755) == 0;
	
	L0Log(@"exe = %@, needs auth = %d", exe, needsAuth);
	return needsAuth;
}

- (BOOL) authorizeAndReturnError:(NSError**) error requiresRestart:(BOOL*) restart {
	if (restart) *restart = NO;
	
	if (![self requiresAuthorizationWithError:error])
		return NO;
	
	AuthorizationItem items[] = {
		{ kAuthorizationRightExecute, 0, NULL, 0 }
	};
	
	AuthorizationRights rights = { 1, items };
	AuthorizationRef auth;
	OSStatus err = AuthorizationCreate(&rights, kAuthorizationEmptyEnvironment, kAuthorizationFlagExtendRights | kAuthorizationFlagInteractionAllowed, &auth);
	
	if (err != noErr) {
		if (error) *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:err userInfo:nil];
		return NO;
	}
	
	NSString* exe = [[NSBundle mainBundle] executablePath];
	// exe = [[exe stringByDeletingLastPathComponent] stringByAppendingPathComponent:@"RepairTool"];
	const char* exeC = [exe fileSystemRepresentation];
	const char* chmodArgs[] = { "--PlSAuthorize", NULL };
	
	FILE* pipe;
	err = AuthorizationExecuteWithPrivileges(auth,
											 exeC, 
											 kAuthorizationFlagDefaults, 
											 (char* const*) chmodArgs,
											 &pipe);
	if (err != noErr) {
		AuthorizationFree(auth, kAuthorizationFlagDestroyRights);
		if (error) *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:err userInfo:nil];
		return NO;
	}
	
	char returnSignal;
	while (!feof(pipe))
		fread(&returnSignal, sizeof(char), 1, pipe);
	
	AuthorizationFree(auth, kAuthorizationFlagDestroyRights);
	if (restart) *restart = YES; // TODO
	
	return YES;
}

@end
